package edu.uta.cfl.console;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;

import edu.uta.cfl.GUI.BEN;
import edu.uta.cfl.data.Combo;
import edu.uta.cfl.data.IterationResult;
import edu.uta.cfl.data.SUT;
import edu.uta.cfl.data.SUT.SUTState;
import edu.uta.cfl.engine.ComboManager;
import edu.uta.cfl.engine.IterationOutput;
import edu.uta.cfl.engine.SUTInfoReader;
import edu.uta.cfl.engine.SUTInfoWriter;
import edu.uta.cfl.engine.SUTManager;
import edu.uta.cfl.engine.UpdateTestSet;
import edu.uta.cfl.util.Constants;
import edu.uta.cfl.util.Util;

public class CFL {

	public static SUT sut;
	public static int curCmbLen;
	public static IterationResult iteration1; // testing data
	public static IterationResult iteration2;
	// public static int approachState;
	public static int itr;
	// Changes by jagan - begins ( *AbJ)
	public static BEN ben;

	public static void main(String[] args) {
		BufferedReader stdin = new BufferedReader(new InputStreamReader(
				System.in));

		String inpuFile;
		String outSpc;
		String outTestset;

		try {

			System.out.println("Enter the input file (initial test set): ");
			while ((inpuFile = stdin.readLine()).length() == 0)
				;

			System.out
					.println("\nEnter the output file for Suspicious combos: ");
			while ((outSpc = stdin.readLine()).length() == 0)
				;

			System.out.println("\nEnter the output file for new test cases: ");
			while ((outTestset = stdin.readLine()).length() == 0)
				;

			/*
			 * String inputDir; System.out.println ("Enter the path: "); while
			 * ((inputDir = stdin.readLine()).length()==0);
			 *
			 * System.out.println ("\nEnter the initail test set: "); while
			 * ((inpuFile = stdin.readLine()).length()== 0);
			 *
			 * inputDir+="\\"; inpuFile = inputDir+inpuFile; outSpc =
			 * inputDir+"cmb1.txt"; outTestset = inputDir+"test1.txt";
			 * //Experiments- end
			 */
			processLoad(inpuFile, outSpc, outTestset);

			itr = 0;
			while (true) {
				String input;
				boolean add = false;
				do {
					System.out
							.println("Press A to add exeution status of new test cases, or Press E to exit: ");
					while ((input = stdin.readLine()).length() == 0)
						;
					if (input.toLowerCase().equals("e")) {
						(new SUTInfoWriter(outSpc.substring(0,
								outSpc.lastIndexOf("\\") + 1)
								+ "cmp.txt")).printSuspiciousness(sut,
								curCmbLen);
						System.exit(0);
					}

					else if (input.toLowerCase().equals("a"))
						add = true;
				} while (!add);

				// Experiments- begin
				System.out
						.println("Enter the input file (execution status of new test cases):");
				while ((inpuFile = stdin.readLine()).length() == 0)
					;

				System.out
						.println("\nEnter the output file for Suspicious combos:");
				while ((outSpc = stdin.readLine()).length() == 0)
					;

				System.out
						.println("\nEnter the output file for new test cases: ");
				while ((outTestset = stdin.readLine()).length() == 0)
					;

				/*
				 * System.out.println ("Enter the previous level:"); while
				 * ((inpuFile = stdin.readLine()).length()==0);
				 *
				 * int tmp = Integer.parseInt(inpuFile)+1; outSpc =
				 * inputDir+"cmb"+tmp+".txt"; outTestset =
				 * inputDir+"test"+tmp+".txt";
				 *
				 * inpuFile = inputDir+"test"+inpuFile+".txt"; //Experiments-
				 * end
				 */
				processAddTest(inpuFile, outSpc, outTestset);
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	public static void processLoad(String input, String outSpc,
			String outTestset) {
		sut = new SUT();
		iteration1 = new IterationResult(); // test data
		sut = (new SUTInfoReader(input)).getSUT();
		curCmbLen = sut.getStrength();
		SUTManager.approach(sut, sut.getStrength(), Constants.APPROACH_LOAD);

		// approachState = Constants.APPROACH_ADD;
		ArrayList<int[]> tcList = new ArrayList<int[]>();

		if (sut.getStatus() == SUTState.expansion) {
			sut.setStatus(SUTState.expansion);
			int len = curCmbLen;
			while ((sut.getStatus() == SUTState.expansion)
					&& len < Constants.maxIndStr - 1)
				SUTManager.expandCmb(sut, len++);

			curCmbLen = len;

			if (len < Constants.maxIndStr - 1)
				tcList = SUTManager.generateNewTC(sut, curCmbLen);
			else
				sut.setStatus(SUTState.notFound);

			itr = 0;
		} else
			tcList = SUTManager.generateNewTC(sut, sut.getStrength());
		System.out.println("*******"+sut.getStatus().toString());
		if (sut.getStatus() == SUTState.continuing) {
			(new SUTInfoWriter(outTestset)).printTCList(tcList,
					sut.getParameters());
			(new SUTInfoWriter(outSpc)).printSUT(sut, curCmbLen);
			// new logic start
			int len = sut.getStrength();
			iteration1.setTestSet(tcList);
			iteration1.setSuspiciousCombos(sut.getSuspiciousCombos(curCmbLen));
			iteration1.setSuspiciousComponents(sut.getSuspiciousComponents(curCmbLen));
			for(int i=0;i<tcList.size();i++)
			{
				System.out.println("Testing testing *******"+ Arrays.toString(iteration1.getTestSet().get(i)));
				//System.out.println("Testing testing ******"+Arrays.toString(iteration1.getSuspiciousCombinations().))
			}
			//new IterationOutput().printSuspiciousCombinations(sut, iteration1, curCmbLen);
			IterationOutput printOutput = new IterationOutput();
			printOutput.printSuspiciousCombinations(sut, iteration1, curCmbLen);
			printOutput.printSuspiciousComponent(sut, iteration1, curCmbLen);
			printOutput.printRecommendedTestSet(sut, iteration1);
			//new logic ends
		} else {
			(new SUTInfoWriter(outSpc)).printSUT(sut, curCmbLen);
			(new SUTInfoWriter(
					outSpc.substring(0, outSpc.lastIndexOf("\\") + 1)
							+ "cmp.txt")).printSuspiciousness(sut, curCmbLen);
		}

		printOutput(sut.getStatus(), outTestset);
	}

	public static void processAddTest(String input, String outSpc,
			String outTestset) {

		int level = Collections.max(sut.getTs().getLevelAdded()) + 1;

		(new SUTInfoReader(input)).addTestSet(sut);

		// new logic starts
		/*
		iteration2 = new IterationResult();
		new UpdateTestSet(sut,iteration1).addTestSet();
		*/
		// new logic ends

		int tsCnt = 0;
		int passCnt = 0;

		ArrayList<Integer> idxLst = new ArrayList<Integer>();
		for (int i = 0; i < sut.getTs().getMatrix().size(); i++) {
			if (sut.getTs().getLevelAdded().get(i) == level) {
				idxLst.add(i);
			}
		}

		if (idxLst.size() == 0) {
			Util.showMsg("There is no test case or result in " + input);
			return;
		}

		for (int i : idxLst) {
			if (sut.getTs().getResult().get(i) == sut.getTs().PASS) {
				passCnt++;
			}

		}

		ArrayList<int[]> tcList = new ArrayList<int[]>();

		SUTManager.approach(sut, curCmbLen, Constants.APPROACH_ADD);
		for (Combo cmb : sut.getTestGen4TheseCmb()) {
			int i = ComboManager.isCmbInCmbLst(cmb,
					sut.getSuspiciousCombos(curCmbLen));
			if (i != -1) {
				sut.getSuspiciousCombos(curCmbLen).get(i).setFailInd(true);
				sut.setStatus(SUTState.failureInducing);
			}
		}

		if (sut.getStatus() != SUTState.failureInducing) {
			if (curCmbLen < Constants.maxIndStr) {
				if (itr < Constants.itrNum) {
					itr++;

					tcList = SUTManager.generateNewTC(sut, curCmbLen);
					if (passCnt == 0 && sut.getStatus() == SUTState.continuing)
						sut.setStatus(SUTState.noImprovement);

				}
			}

			if (itr == Constants.itrNum
					|| sut.getStatus() == SUTState.expansion) {
				if (curCmbLen < Constants.maxIndStr) {
					sut.setStatus(SUTState.expansion);
					int len = curCmbLen;
					while ((sut.getStatus() == SUTState.expansion))
						SUTManager.expandCmb(sut, len++);

					curCmbLen = len;
					if (len < Constants.maxIndStr)
						tcList = SUTManager.generateNewTC(sut, curCmbLen);
					else
						sut.setStatus(SUTState.InducingTest);

				}
				itr = 0;

			}

		}

		if (sut.getStatus() == SUTState.continuing) {
			(new SUTInfoWriter(outTestset)).printTCList(tcList,
					sut.getParameters());
			(new SUTInfoWriter(outSpc)).printSUT(sut, curCmbLen);
			//new logic starts

			iteration2.setTestSet(tcList);
			iteration2.setSuspiciousCombos(sut.getSuspiciousCombos(curCmbLen));
			iteration2.setSuspiciousComponents(sut.getSuspiciousComponents(curCmbLen));
			for(int i=0;i<tcList.size();i++)
			{
				System.out.println("Testing testing *******"+ Arrays.toString(iteration2.getTestSet().get(i)));
				//System.out.println("Testing testing ******"+Arrays.toString(iteration1.getSuspiciousCombinations().))
			}
			//new IterationOutput().printSuspiciousCombinations(sut, iteration1, curCmbLen);
			IterationOutput printOutput2 = new IterationOutput();
			printOutput2.printSuspiciousCombinations(sut, iteration1, curCmbLen);
			printOutput2.printSuspiciousComponent(sut, iteration1, curCmbLen);
			printOutput2.printRecommendedTestSet(sut, iteration1);

			//new logic ends

		} else {
			(new SUTInfoWriter(outSpc)).printSUT(sut, curCmbLen);
			(new SUTInfoWriter(
					outSpc.substring(0, outSpc.lastIndexOf("\\") + 1)
							+ "cmp.txt")).printSuspiciousness(sut, curCmbLen);

		}

		Util.showMsg("\n" + idxLst.size() + " new test cases have been added.");

		printOutput(sut.getStatus(), outTestset);
		(new SUTInfoWriter(outSpc.substring(0, outSpc.lastIndexOf("\\") + 1)
				+ "cmp" + level + ".txt")).printSuspiciousness(sut, curCmbLen);

	}

	public static void printOutput(SUTState appResult, String fileName) {
		(new SUTInfoWriter()).summarizeOutpou(sut, curCmbLen);

		if (appResult == SUTState.continuing)
			Util.showMsg("\nTo increase the confidence of suspicious combos, it is recommended to execute new test cases in \n"
					+ fileName + ".\n");
		else if (appResult == SUTState.notFound) {
			Util.showMsg("\n"
					+ "All tests fails and all combos are failure-inducing. \n");
			System.exit(0);
		} else if (appResult == SUTState.noImprovement) {
			Util.showMsg("\n" + "Adding tests makes no improvement. \n");
			System.exit(0);
		} else if (appResult == SUTState.InducingTest) {
			Util.showMsg("\nNo inducing combination, failed tests are inducing.");
			Util.showMsg("\nEnd.");
			System.exit(0);
		}

		else {
			Util.showMsg("\nEnd.");
			System.exit(0);
		}
	}

}
